using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using log4net;
using System.Security.Cryptography;
//using NFine.Code;

namespace GZ.Projects.WCS_SVC
{
	public class HttpClient
	{
		//private ILog logger = log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
		public HttpClient()
		{
		}
			/// <summary>
		/// http client
		/// </summary>
		/// <param name="type">请求类型:get,post</param>
		/// <param name="param"></param>
		/// <param name="url"></param>
		/// <param name="errorMsg"></param>
		/// <param name="statusCode"></param>
		/// <returns></returns>
		public string Call(string type, string param, string url, out string errorMsg, out int statusCode)
    {
        statusCode = 0;
        errorMsg = string.Empty;
        try
        {
            HttpWebRequest request = WebRequest.CreateHttp(url) as HttpWebRequest;
            request.Method = type.ToUpper();
            request.ContentType = "application/json";
            request.Timeout = 15000;
            request.AllowAutoRedirect = false;
            
            if (request.Method == "POST" || request.Method == "PUT")
            {
                byte[] byts = Encoding.UTF8.GetBytes(param);
                request.ContentLength = byts.Length;
                using (Stream s = request.GetRequestStream())
                {
                    s.Write(byts, 0, byts.Length);
                }
            }
            
            using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
            {
                statusCode = (int)response.StatusCode;
                using (Stream s = response.GetResponseStream())
                {
                    using (StreamReader sr = new StreamReader(s))
                    {
                        string json = sr.ReadToEnd();
                        return json; 
                    }
                }
            }
        }
        catch (WebException ex)
        {
            string text = string.Empty;
            if (ex.Response is HttpWebResponse errorResponse) 
            {
                statusCode = (int)errorResponse.StatusCode;
                if (ex.Status == WebExceptionStatus.ProtocolError && errorResponse.GetResponseStream() != null)
                {
                    using (Stream data = errorResponse.GetResponseStream())
                    using (var reader = new StreamReader(data))
                    {
                        text = reader.ReadToEnd();
                    }
                }
            }
            else if (ex.Status == WebExceptionStatus.Timeout)
            {
                statusCode = (int)HttpStatusCode.RequestTimeout; 
            }
            else 
            {
	            statusCode = (int)HttpStatusCode.ServiceUnavailable;
            }
            errorMsg = ex.Message;
            return text;
        }
        catch (Exception e) 
        {
            errorMsg = e.Message;
            statusCode = (int)HttpStatusCode.InternalServerError; // 500
            return string.Empty;
        }
    }
		/// <summary>
		/// http client
		/// </summary>
		/// <param name="type">请求类型:get,post</param>
		/// <param name="param"></param>
		/// <param name="url"></param>
		/// <param name="errorMsg"></param>
		/// <returns></returns>
		public string Call( string param, string url, out string errorMsg)
		{
			errorMsg = string.Empty;
			try
			{
				HttpWebRequest request = WebRequest.CreateHttp(url) as HttpWebRequest;
				request.Method = "POST";
				request.ContentType = "application/json";
				request.Timeout = 150000;
				request.AllowAutoRedirect = false;
				
                request.Headers.Add("AppKey", "OpenInfo");
                long currentTimeStamp = (long)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
                request.Headers.Add("ReqTime", currentTimeStamp.ToString());
                string secret = "OpenInfoOpenInfoSecret";
                string dataToHash = secret + currentTimeStamp.ToString();
                string reqVerify = CalculateMD5Hash(dataToHash);
                request.Headers.Add("ReqVerify", reqVerify);

				byte[] byts = Encoding.UTF8.GetBytes(param);
				request.ContentLength = byts.Length;
				using (Stream s = request.GetRequestStream())
				{
					s.Write(byts, 0, byts.Length);
				}
				using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
				{
					using (Stream s = response.GetResponseStream())
					{
						using (StreamReader sr = new StreamReader(s))
						{
							string json = sr.ReadToEnd();
							return json;
						}
					}
				}
			}
			catch (WebException ex)
			{
				string text = string.Empty;
				if (ex.Status == WebExceptionStatus.ProtocolError)
				{
					using (Stream data = ex.Response.GetResponseStream())
						using (var reader = new StreamReader(data))
					{
						text = reader.ReadToEnd();
					}
				}
				errorMsg = ex.Message;
				return text;
			}
		}
		
		public string CalculateMD5Hash(string input)
        {
            using (MD5 md5 = MD5.Create())
            {
                byte[] inputBytes = Encoding.UTF8.GetBytes(input);
                byte[] hashBytes = md5.ComputeHash(inputBytes);

                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < hashBytes.Length; i++)
                {
                    sb.Append(hashBytes[i].ToString("x2"));
                }

                return sb.ToString();
            }
        }
		/// <summary>
		/// http client
		/// </summary>
		/// <param name="type">请求类型:get,post</param>
		/// <param name="param"></param>
		/// <param name="url"></param>
		/// <param name="errorMsg"></param>
		/// <returns></returns>
		public string Call(string type, string param, string url, out string errorMsg)
		{
			errorMsg = string.Empty;
			try
			{
				HttpWebRequest request = WebRequest.CreateHttp(url) as HttpWebRequest;
				request.Method = type;
				request.ContentType = "application/json";
				request.Timeout = 30000;
				request.AllowAutoRedirect = false;
				if (type == "post" || type == "put")
				{
					byte[] byts = Encoding.UTF8.GetBytes(param);
					request.ContentLength = byts.Length;
					using (Stream s = request.GetRequestStream())
					{
						s.Write(byts, 0, byts.Length);
					}
				}
				using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
				{
					using (Stream s = response.GetResponseStream())
					{
						using (StreamReader sr = new StreamReader(s))
						{
							string json = sr.ReadToEnd();
							return json;
						}
					}
				}
			}
			catch (WebException ex)
			{
				string text = string.Empty;
				if (ex.Status == WebExceptionStatus.ProtocolError)
				{
					using (Stream data = ex.Response.GetResponseStream())
						using (var reader = new StreamReader(data))
					{
						text = reader.ReadToEnd();
					}
				}
				errorMsg = ex.Message;
				return text;
			}
		}
		
		/// <summary>
		/// Post请求
		/// </summary>
		public async Task<Tuple<string,string>> HttpPostAsync(string url, string param)
		{
			var errorMsg = string.Empty;
			try
			{
				HttpWebRequest request = WebRequest.CreateHttp(url) as HttpWebRequest;
				request.Method = "POST";
				request.ContentType = "application/json";
				request.Timeout = 150000;
				request.AllowAutoRedirect = false;
				byte[] byts = Encoding.UTF8.GetBytes(param);
				request.ContentLength = byts.Length;
				//using (Stream s = await request.GetRequestStreamAsync())
				//{
				//	s.Write(byts, 0, byts.Length);
				//}
				Stream srequest = await request.GetRequestStreamAsync().ConfigureAwait(false);
				srequest.Write(byts, 0, byts.Length);
				srequest.Close();
				srequest.Dispose();

				HttpWebResponse response = request.GetResponse() as HttpWebResponse;
				Stream s = response.GetResponseStream();
				StreamReader sr = new StreamReader(s);
				string json = sr.ReadToEnd();

				s.Close();
				s.Dispose();
				sr.Close();
				sr.Dispose();

				return new Tuple<string, string>(json, errorMsg);

			}
			catch (WebException ex)
			{
				string text = string.Empty;
				if (ex.Status == WebExceptionStatus.ProtocolError)
				{
					using (Stream data = ex.Response.GetResponseStream())
					using (var reader = new StreamReader(data))
					{
						text = reader.ReadToEnd();
					}
				}
				errorMsg = ex.Message;
				return new Tuple<string, string>(text, errorMsg);
			}
		}

		public async Task<string> CallAsync(string type, string param, string url)
		{
			HttpWebRequest request = WebRequest.CreateHttp(url) as HttpWebRequest;
			try
			{
				request.Method = type;
				request.ContentType = "application/json";
				request.Timeout = 150000;
				request.AllowAutoRedirect = false;
				if (type == "post" || type == "put")
				{
					byte[] byts = Encoding.UTF8.GetBytes(param);
					request.ContentLength = byts.Length;
					using (Stream s = request.GetRequestStream())
					{
						s.Write(byts, 0, byts.Length);
					}
				}

				using(var response = request.GetResponseAsync().Result as HttpWebResponse)
				{
					using(var s = response.GetResponseStream())
					{
						using(var sr = new StreamReader(s))
						{
							return await sr.ReadToEndAsync().ConfigureAwait(false);
						}
					}
				}
				
			}
			catch (Exception)
			{
				// logger.Error($"HTTP数据异常.{ex.Message}");
				return null;
			}
			finally
			{
				request.Abort();
			}
		}
			
		/// <summary>
		/// Post请求
		/// </summary>
		public string HttpPost(string url, string param, out string errorMsg)
		{
			errorMsg = string.Empty;
			HttpWebRequest request = null;
			try
			{
				request = WebRequest.CreateHttp(url) as HttpWebRequest;
				request.Method = "POST";
				request.ContentType = "application/json";
				request.Timeout = 8000;
				request.AllowAutoRedirect = false;
				byte[] byts = Encoding.UTF8.GetBytes(param);
				request.ContentLength = byts.Length;
				using (Stream s = request.GetRequestStream())
				{
					s.Write(byts, 0, byts.Length);
				}
				using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
				{
					using (Stream s = response.GetResponseStream())
					{
						using (StreamReader sr = new StreamReader(s))
						{
							string json = sr.ReadToEnd();
							return json;
						}
					}
				}
			}
			catch (WebException ex)
			{
				string text = string.Empty;
				if (ex.Status == WebExceptionStatus.ProtocolError)
				{
					using (Stream data = ex.Response.GetResponseStream())
					using (var reader = new StreamReader(data))
					{
						text = reader.ReadToEnd();
					}
				}
				errorMsg = ex.Message;
				return text;
			}
		}
	}
}